package cn.hg.base.jfinal.controller;

import cn.hg.base.kit.RequestKit;
import cn.hg.jfsa.web.theme.ThemeRender;
import com.jfinal.core.Controller;
import com.jfinal.core.NotAction;
import com.jfinal.json.FastJson;
import com.jfinal.json.Json;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.Kv;
import com.jfinal.render.Render;
import com.jfinal.upload.UploadFile;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 基础Controller，里面的很多方法是从JBoot中照搬过来的
 *
 * @author Golly
 */
public abstract class BaseController extends Controller {

	private static final Object NULL_OBJ = new Object();
	private static final String BODY_STRING_ATTR = "__body_str";
	private String rawData;

	/**
	 * 获取当前网址
	 *
	 * @return
	 */
	@NotAction
	public String getBaseUrl() {
		HttpServletRequest req = getRequest();
		int port = req.getServerPort();

		return port == 80 ? String.format("%s://%s%s", req.getScheme(), req.getServerName(), req.getContextPath())
				: String.format("%s://%s%s%s", req.getScheme(), req.getServerName(), ":" + port, req.getContextPath());

	}

	@NotAction
	public String getBodyString() {
		Object object = getAttr(BODY_STRING_ATTR);
		if (object == NULL_OBJ) {
			return null;
		}

		if (object != null) {
			return (String) object;
		}

		object = HttpKit.readData(getRequest());
		if (object == null) {
			setAttr(BODY_STRING_ATTR, NULL_OBJ);
		} else {
			setAttr(BODY_STRING_ATTR, object);
		}

		return (String) object;
	}

	/**
	 * 获取ip地址
	 *
	 * @return
	 */
	@NotAction
	public String getIPAddress() {
		return RequestKit.getIpAddress(getRequest());
	}

	/**
	 * 将前端传入的参数包装成KV，方便查询时使用
	 *
	 * @return
	 */
	@NotAction
	public Kv getParaMapToKv() {
		Kv kv = Kv.create();

		for (String key : this.getParaMap().keySet()) {
			// kv.set(key, this.getParaMap().get(key));
			kv.set(key, this.getPara(key));
		}

		return kv;
	}

	/**
	 * 获取 http 请求 body 中的原始数据，通常用于接收 json String 这类数据
	 * <p>
	 * 可多次调用此方法，避免掉了 HttpKit.readData(...) 方式获取该数据时多次调用 引发的异常
	 *
	 * @return http 请求 body 中的原始数据
	 */
	@NotAction
	public String getRawData() {
		if (rawData == null) {
			rawData = com.jfinal.kit.HttpKit.readData(this.getRequest());
		}
		return rawData;
	}

	/**
	 * @param targetClass
	 * @return
	 */
	@NotAction
	public <T> T getRawDataTo(Class<T> targetClass) {
		Json json = Json.getJson();
		if (json instanceof com.jfinal.json.JFinalJson) {
			return FastJson.getJson().parse(getRawData(), targetClass);
		} else {
			return json.parse(getRawData(), targetClass);
		}
	}

	/**
	 * @return
	 */
	@NotAction
	public Kv getRawDataToKv() {
		return getRawDataTo(Kv.class);
	}

	/**
	 * 获取 referer
	 *
	 * @return
	 */
	@NotAction
	public String getReferer() {
		return RequestKit.getReferer(getRequest());
	}

	/**
	 * 获取所有上传的文件
	 *
	 * @return
	 */
	@NotAction
	public HashMap<String, UploadFile> getUploadFilesMap() {
		if (!isMultipartRequest()) {
			return null;
		}

		List<UploadFile> fileList = getFiles();
		HashMap<String, UploadFile> filesMap = null;
		if (fileList != null && fileList.size() > 0) {
			filesMap = new HashMap<String, UploadFile>();
			for (UploadFile ufile : fileList) {
				filesMap.put(ufile.getParameterName(), ufile);
			}
		}
		return filesMap;
	}

	/**
	 * 获取ua
	 *
	 * @return
	 */
	@NotAction
	public String getUserAgent() {
		return RequestKit.getUserAgent(getRequest());
	}

	/**
	 * 默认的Index方法
	 */
	public abstract void index();

	/**
	 * 是否是ajax请求
	 *
	 * @return
	 */
	@NotAction
	public boolean isAjaxRequest() {
		return RequestKit.isAjaxRequest(getRequest());
	}

	/**
	 * 是否是IE浏览器
	 *
	 * @return
	 */
	@NotAction
	public boolean isIEBrowser() {
		return RequestKit.isIEBrowser(getRequest());
	}

	/**
	 * 是否是手机浏览器
	 *
	 * @return
	 */
	@NotAction
	public boolean isMoblieBrowser() {
		return RequestKit.isMoblieBrowser(getRequest());
	}

	/**
	 * 是否是multpart的请求（带有文件上传的请求）
	 *
	 * @return
	 */
	@NotAction
	public boolean isMultipartRequest() {
		return RequestKit.isMultipartRequest(getRequest());
	}

	/**
	 * 是否是微信浏览器
	 *
	 * @return
	 */
	@NotAction
	public boolean isWechatBrowser() {
		return RequestKit.isWechatBrowser(getRequest());
	}

	@NotAction
	public void renderAjaxFailed(String code, String msg) {
		renderAjaxFailed(code, msg, null);
	}

	@NotAction
	public void renderAjaxFailed(String code, String msg, Kv kv) {
		Map<String, Object> retMap = new HashMap<>();
		retMap.put("code", code);
		retMap.put("msg", msg);

		if (kv != null) {
			for (Object key : kv.keySet()) {
				retMap.put((String) key, kv.get(key));
			}
		}

		this.renderJson(retMap);
	}

	@NotAction
	public void renderAjaxSuccessed() {
		this.renderAjaxFailed("0", null, null);
	}

	@NotAction
	public void renderAjaxSuccessed(Kv kv) {
		this.renderAjaxFailed("0", null, kv);
	}

	@NotAction
	public boolean isPostRequest() {
		return RequestKit.isPostRequest(this.getRequest());
	}

	@NotAction
	public void renderTheme(String view) {
		Render render = new ThemeRender(view);
		this.render(render);
	}
}
